import torch
from torch.utils.tensorboard import SummaryWriter
from pathlib import Path
import shutil

def accuracy(output, target, topk=(1,)):
    """Computes the accuracy over the k top predictions for the specified values of k"""
    with torch.no_grad():
        maxk = max(topk)
        batch_size = target.size(0)

        _, pred = output.topk(maxk, 1, True, True)
        pred = pred.t()
        correct = pred.eq(target.view(1, -1).expand_as(pred))

        res = []
        for k in topk:
            correct_k = correct[:k].reshape(-1).float().sum(0, keepdim=True)
            res.append(correct_k.mul_(100.0 / batch_size))
        return res


def tb_write_scalars(data, writer: SummaryWriter, epoch=None, step=None):
    t = epoch if epoch is not None else step
    for k, v in data.items():
        writer.add_scalar(k, v, t)


def save_checkpoint(state, save_dir: Path, is_best):
    filename = save_dir / "last.pt"
    torch.save(state, filename)
    if is_best:
        tgt_fname = save_dir / 'best.pt'
        shutil.copyfile(filename, str(tgt_fname))
